package com.gitee.melin.bee.util;

import com.google.common.collect.Lists;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;

public class SqlUtils {

    /** 清除sql中多行和单行注释 已经空行 */
    public static String cleanSqlComment(String sql) {
        boolean singleLineComment = false;
        List<Character> chars = Lists.newArrayList();
        List<Character> delChars = Lists.newArrayList();
        List<Character> lineChars = Lists.newArrayList();

        char preCh = 0;
        Character quote = null;
        char lastChar = 0;
        for (int i = 0, len = sql.length(); i < len; i++) {
            char ch = sql.charAt(i);
            if (i != 0) {
                lastChar = sql.charAt(i - 1);
            }

            if (ch == '\'') {
                if (quote == null) {
                    quote = ch;
                } else if (quote == '\'' && lastChar != '\\') {
                    quote = null;
                }
            } else if (ch == '"') {
                if (quote == null) {
                    quote = ch;
                } else if (quote == '"' && lastChar != '\\') {
                    quote = null;
                }
            }

            if ((i + 1) < len) {
                char nextCh = sql.charAt(i + 1);
                if (quote == null) { // 避免字符串中出现 --
                    if (ch == '-' && nextCh == '-' && !singleLineComment) {
                        if (i > 0) {
                            preCh = sql.charAt(i - 1);
                        }
                        singleLineComment = true;
                    }
                }
            }

            if (!singleLineComment) {
                lineChars.add(ch);
            }

            if (ch == '\n') {
                if (singleLineComment) {
                    singleLineComment = false;
                    if (preCh != ch) {
                        lineChars.add(ch);
                    }

                    String line = StringUtils.join(lineChars, "");
                    if (StringUtils.isNotBlank(line)) {
                        chars.addAll(lineChars);
                    }
                } else {
                    chars.addAll(lineChars);
                }

                lineChars.clear();
            }
        }
        chars.addAll(lineChars);

        sql = StringUtils.join(chars, "");

        chars = Lists.newArrayList();
        boolean mutilLineComment = false;
        for (int i = 0, len = sql.length(); i < len; i++) {
            char ch = sql.charAt(i);

            if ((i + 2) < len) {
                char nextCh1 = sql.charAt(i + 1);
                char nextCh2 = sql.charAt(i + 2);
                if (ch == '/' && nextCh1 == '*' && nextCh2 != '+' && !mutilLineComment) {
                    mutilLineComment = true;
                }
            }

            if (!mutilLineComment) {
                chars.add(ch);

                if (delChars.size() > 0) {
                    delChars.clear();
                }
            } else {
                delChars.add(ch);
            }

            if ((i + 1) < len) {
                char nextCh1 = sql.charAt(i + 1);
                if (mutilLineComment && ch == '*' && nextCh1 == '/') {
                    mutilLineComment = false;
                    i++;
                }
            }
        }

        if (mutilLineComment) {
            chars.addAll(delChars);
            delChars.clear();
        }

        return cleanBlankLine(StringUtils.join(chars, ""));
    }

    /** 多个sql语句逗号分隔拆开 */
    public static List<String> splitMultiSql(String sql) {
        List<String> sqls = Lists.newArrayList();

        Character quote = null;
        char lastChar = 0;
        int lastIndex = 0;
        for (int i = 0, len = sql.length(); i < len; i++) {
            char ch = sql.charAt(i);
            if (i != 0) {
                lastChar = sql.charAt(i - 1);
            }

            if (ch == '\'') {
                if (quote == null) {
                    quote = ch;
                } else if (quote == '\'' && lastChar != '\\') {
                    quote = null;
                }
            } else if (ch == '"') {
                if (quote == null) {
                    quote = ch;
                } else if (quote == '"' && lastChar != '\\') {
                    quote = null;
                }
            } else if (ch == ';' && quote == null) {
                String content = StringUtils.substring(sql, lastIndex, i).trim();
                if (StringUtils.isNotBlank(content)) {
                    sqls.add(content);
                }
                lastIndex = i + 1;
            }
        }

        String content = StringUtils.substring(sql, lastIndex).trim();
        if (StringUtils.isNotBlank(content)) {
            sqls.add(content);
        }

        return sqls;
    }

    public static String cleanBlankLine(String sql) {
        sql = StringUtils.trim(sql);
        if (StringUtils.isBlank(sql)) {
            return sql;
        }

        String[] lines = sql.split("\\r?\\n");
        return Arrays.stream(lines).filter(StringUtils::isNotBlank).collect(Collectors.joining("\r\n"));
    }

    public static void main(String[] args) {
        String sql = "\n" + "\n"
                + "select * from users\n"
                + "\n"
                + "\n"
                + "\n"
                + "\n"
                + "\n"
                + "alter table\n"
                + "\n"
                + "\n"
                + "\n"
                + "\n";
        System.out.println(cleanSqlComment(sql));
    }
}
